package utils;

import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.util.Map;
import java.util.Map.Entry;

public class NativeEvidenceHttpClient {
	/** 连接超时时间 */
	private static final int CONNECT_TIMEOUT = 6 * 1000;
	/** 读取超时时间 */
	private static final int READ_TIMEOUT = 6 * 1000;

	/**
	 * get请求
	 * 
	 * @param url
	 * @param map
	 *            请求Map参数，{"name1":"value1","name2":"value2"}的形式。
	 * @param charset
	 *            字符集编码
	 * @param authHmac
	 *            请求头中的签名值
	 * @return
	 */
	public static String sendGet(String url, Map<String, Object> map, String charset, String authHmac) {
		StringBuffer sb = new StringBuffer();
		// 构建请求参数
		if (map != null && map.size() > 0) {
			for (Entry<String, Object> e : map.entrySet()) {
				sb.append(e.getKey());
				sb.append("=");
				sb.append(e.getValue());
				sb.append("&");
			}
		}
		return sendGet(url, sb.toString(), charset, authHmac);
	}

	/**
	 * POST 请求，不支持发送文件，如发送文件，请调用{@link #postWithFile(String, Map, Map, String)}
	 * 方法
	 * 
	 * @param url
	 * @param map
	 *            请求Map参数，{"name1":"value1","name2":"value2"}的形式。
	 * @param charset
	 * @param authHmac
	 * @return
	 */
	public static String sendPost(String url, Map<String, Object> map, String charset, String authHmac) {
		StringBuffer sb = new StringBuffer();
		// 构建请求参数
		if (map != null && map.size() > 0) {
			for (Entry<String, Object> e : map.entrySet()) {
				sb.append(e.getKey());
				sb.append("=");
				sb.append(e.getValue());
				sb.append("&");
			}
		}
		return sendPost(url, sb.toString(), charset, authHmac);
	}

	/**
	 * get请求
	 * 
	 * @param url
	 * @param param
	 *            请求参数， name1=value1&name2=value2 的形式
	 * @param charset
	 * @param authHmac
	 * @return
	 */
	public static String sendGet(String url, String param, String charset, String authHmac) {
		String result = "";
		String line;
		StringBuffer sb = new StringBuffer();
		BufferedReader in = null;
		try {
			String urlNameString = url + "?" + param;
			URL realUrl = new URL(urlNameString);
			// 打开和URL之间的连接
			URLConnection conn = realUrl.openConnection();
			// 设置通用的请求属性 设置请求格式
			if (null != authHmac && !"".equals(authHmac)) {
				conn.setRequestProperty("authHmac", authHmac);
			}
			conn.setRequestProperty("contentType", charset);
			conn.setRequestProperty("content-type", "application/x-www-form-urlencoded");
			// 设置超时时间
			conn.setConnectTimeout(CONNECT_TIMEOUT);
			conn.setReadTimeout(READ_TIMEOUT);
			// 建立实际的连接
			conn.connect();
			// 定义 BufferedReader输入流来读取URL的响应,设置接收格式
			in = new BufferedReader(new InputStreamReader(conn.getInputStream(), charset));
			while ((line = in.readLine()) != null) {
				sb.append(line);
			}
			result = sb.toString();
		} catch (Exception e) {
			System.out.println("发送GET请求出现异常！" + e);
			e.printStackTrace();
		}
		// 使用finally块来关闭输入流
		finally {
			try {
				if (in != null) {
					in.close();
				}
			} catch (Exception e2) {
				e2.printStackTrace();
			}
		}
		return result;
	}

	/**
	 * post请求
	 * 
	 * @param url
	 * @param param
	 *            请求参数，请求参数应该是 name1=value1&name2=value2 的形式。
	 * @param charset
	 * @param authHmac
	 * @return
	 */
	public static String sendPost(String url, String param, String charset, String authHmac) {
		PrintWriter out = null;
		BufferedReader in = null;
		String result = "";
		String line;
		StringBuffer sb = new StringBuffer();
		try {
			URL realUrl = new URL(url);
			// 打开和URL之间的连接
			URLConnection conn = realUrl.openConnection();
			// 设置通用的请求属性 设置请求格式
			if (null != authHmac && !"".equals(authHmac)) {
				conn.setRequestProperty("authHmac", authHmac);
			}
			conn.setRequestProperty("contentType", charset);
			conn.setRequestProperty("content-type", "application/x-www-form-urlencoded");
			// 设置超时时间
			conn.setConnectTimeout(CONNECT_TIMEOUT);
			conn.setReadTimeout(READ_TIMEOUT);
			// 发送POST请求必须设置如下两行
			conn.setDoOutput(true);
			conn.setDoInput(true);
			// 获取URLConnection对象对应的输出流
			out = new PrintWriter(conn.getOutputStream());
			// 发送请求参数
			out.print(param);
			// flush输出流的缓冲
			out.flush();
			// 定义BufferedReader输入流来读取URL的响应 设置接收格式
			in = new BufferedReader(new InputStreamReader(conn.getInputStream(), charset));
			while ((line = in.readLine()) != null) {
				sb.append(line);
			}
			result = sb.toString();
		} catch (Exception e) {
			System.out.println("发送 POST请求出现异常!" + e);
			e.printStackTrace();
		}
		// 使用finally块来关闭输出流、输入流
		finally {
			try {
				if (out != null) {
					out.close();
				}
				if (in != null) {
					in.close();
				}
			} catch (IOException ex) {
				ex.printStackTrace();
			}
		}
		return result;
	}

	/**
	 * 发送带有文件的post请求
	 * 
	 * @param url
	 * @param params
	 * @param files
	 *            文件
	 * @param authHmac
	 * @return
	 * @throws IOException
	 */
	public static String postWithFile(String url, Map<String, Object> params, Map<String, File> files,
			String authHmac) {

		String result = "";
		String BOUNDARY = java.util.UUID.randomUUID().toString();
		String PREFIX = "--", LINEND = "\r\n";
		String MULTIPART_FROM_DATA = "multipart/form-data";
		String CHARSET = "UTF-8";

		DataOutputStream outStream = null;
		InputStream is = null;
		BufferedReader in = null;

		HttpURLConnection conn = null;
		try {
			URL realUrl = new URL(url);
			// 打开和URL之间的连接
			conn = (HttpURLConnection) realUrl.openConnection();
			conn.setReadTimeout(READ_TIMEOUT); // 缓存的最长时间
			conn.setDoInput(true);// 允许输入
			conn.setDoOutput(true);// 允许输出
			conn.setUseCaches(false); // 不允许使用缓存
			conn.setRequestMethod("POST");
			conn.setRequestProperty("connection", "keep-alive");
			conn.setRequestProperty("Charsert", "UTF-8");
			conn.setRequestProperty("Content-Type", MULTIPART_FROM_DATA + ";boundary=" + BOUNDARY);
			if (null != authHmac && !"".equals(authHmac)) {
				conn.setRequestProperty("authHmac", authHmac);
			}
			// 首先组拼文本类型的参数
			StringBuilder sb = new StringBuilder();
			for (Entry<String, Object> entry : params.entrySet()) {
				sb.append(PREFIX);
				sb.append(BOUNDARY);
				sb.append(LINEND);
				sb.append("Content-Disposition: form-data; name=\"" + entry.getKey() + "\"" + LINEND);
				sb.append("Content-Type: text/plain; charset=" + CHARSET + LINEND);
				sb.append("Content-Transfer-Encoding: 8bit" + LINEND);
				sb.append(LINEND);
				sb.append(entry.getValue());
				sb.append(LINEND);
			}

			outStream = new DataOutputStream(conn.getOutputStream());
			outStream.write(sb.toString().getBytes());

			// 发送文件数据
			if (files != null) {
				for (Entry<String, File> file : files.entrySet()) {
					StringBuilder sb1 = new StringBuilder();
					sb1.append(PREFIX);
					sb1.append(BOUNDARY);
					sb1.append(LINEND);
					// name是post中传参的键 filename是文件的名称
					sb1.append("Content-Disposition: form-data; name=\"file\"; filename=\"" + file.getValue().getName()
							+ "\"" + LINEND);
					sb1.append("Content-Type: application/octet-stream; charset=" + CHARSET + LINEND);
					sb1.append(LINEND);
					outStream.write(sb1.toString().getBytes());

					is = new FileInputStream(file.getValue());
					byte[] buffer = new byte[1024];
					int len = 0;
					while ((len = is.read(buffer)) != -1) {
						outStream.write(buffer, 0, len);
					}

					is.close();
					outStream.write(LINEND.getBytes());
				}

				// 请求结束标志
				byte[] end_data = (PREFIX + BOUNDARY + PREFIX + LINEND).getBytes();
				outStream.write(end_data);
				outStream.flush();
				// 得到响应码
				int res = conn.getResponseCode();
				if (res == 200) {
					String line;
					StringBuilder sb2 = new StringBuilder();
					in = new BufferedReader(new InputStreamReader(conn.getInputStream(), "UTF-8"));
					while ((line = in.readLine()) != null) {
						sb2.append(line);
					}
					result = sb2.toString();
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		} // 使用finally块来关闭输出流、输入流
		finally {
			try {
				if (outStream != null) {
					outStream.close();
				}
				if (in != null) {
					in.close();
				}
				if (conn != null) {
					conn.disconnect();
				}
			} catch (IOException ex) {
				ex.printStackTrace();
			}
		}
		return result;
	}
}
